package ohttp

import (
	"gitee.com/cooge/impush/config"
	"gitee.com/cooge/impush/core"
	"encoding/json"
	"gitee.com/cooge/impush/message"
	"gitee.com/cooge/impush/rest"
	"net"
	"net/http"
	"gitee.com/cooge/impush/xhttp/cache"
	"gitee.com/cooge/impush/xhttp/ohttp/conn"
	"runtime"
	"time"
	log "github.com/sirupsen/logrus"
)

func Start() {
	go goScan()
	hs := NewHttpServer()
	hs.Start()
}

type HttpServer struct {
}

type CallNewConn func(*conn.HttpConn)

func callNewConn(conn *conn.HttpConn) {
	data := cache.GetMessageCache(conn.UserId)
	if data != nil && len(data) > 0 {
		_, err := conn.SendMessages(data)
		if err == nil {
			cache.DeleteMessageCaches(conn.UserId, data)
		}
	}
}

func NewHttpServer() *HttpServer {
	var http HttpServer
	return &http
}

func goScan() {
	deal := config.EX_DEADLINE
	timer1 := time.NewTicker(time.Duration(deal) * time.Second)
	for {
		select {
		case <-timer1.C:
			{
				log.Debug("HTTP","扫描过期用户")
				us := core.GetALLUsers()
				for num, vu := range us {
					ius := core.GetUser(vu)
					for _, v := range ius {
						hh, ok := v.(*conn.HttpConn)
						if ok {
							for _,v:=range hh.ConnArray(){
								h,ok:=v.(*conn.HTCPconn)
								if ok{
									if h.IsExpire(){
										h.Close()
									}
								}
							}
							if hh.InTime.Add(time.Duration(deal) * time.Second).Before(time.Now()) {
									core.DeleteUser(vu, hh)
									cache.DeleteMessageCache(vu)

							}
						}
					}
					if num>>7<<7 == num {
						runtime.Gosched()
					}
				}
			}
		}
	}

}

func (this *HttpServer) Start() {
	http.HandleFunc("/ex", this.exchange)
	http.HandleFunc("/ex/sendmsg", rest.SendMessage)
}
func (this *HttpServer) exchange(w http.ResponseWriter, r *http.Request) {
	this.baseDeal(w, r, callNewConn)
}



/**
入口处理
*/

func (this *HttpServer) baseDeal(w http.ResponseWriter, r *http.Request, cnc CallNewConn) {
	f := r.FormValue("f")
	id := r.FormValue("id")
	if len(id) == 0 {
		h := w.Header()
		h.Add("Access-Control-Allow-Origin", "*")
		w.WriteHeader(404)
		w.Write([]byte(`id can't null`))
	} else if len(f) > 0 {
		h := w.Header()
		h.Add("Access-Control-Allow-Origin", "*")
		w.Write([]byte(`[]`))
	} else {
		data := cache.GetMessageCache(id)
		if data != nil && len(data) > 0 {
			h := w.Header()
			h.Add("Access-Control-Allow-Origin", "*")
			data_ := make([]interface{}, 0)
			for _, dat := range data {
				mdat := make(map[string]interface{})
				mdat[message.FROM] = dat.Heads.Get(message.FROM)
				mdat[message.BODY] = string(dat.Body)
				data_ = append(data_, mdat)
			}
			data, err := json.Marshal(&data_)
			if err == nil {
				w.Write(data)
			} else {
				w.Write([]byte{})
			}
		} else {
			h, ok := w.(http.Hijacker)
			if ok {
				netConn, _, err := h.Hijack()
				if err == nil {
					nc, ok := netConn.(*net.TCPConn)
					if ok {
						httpc := conn.DealHttpConn(nc, id, config.EX_DEADLINE)
						if httpc != nil {
							cnc(httpc)
						} else {
							w.Write([]byte(err.Error()))
						}
					} else {
						netConn.Close()
					}
				} else {
					w.Write([]byte(err.Error()))
				}
			} else {
				w.Write([]byte(`http to socket fail`))
			}
		}
	}
}
